package com.smartwebee.android.blespp.blockly.base;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;

import com.smartwebee.android.blespp.BluetoothLeService;
import com.smartwebee.android.blespp.blockly.BlocklyUtils;
import com.smartwebee.android.blespp.hospital.BaseActivity;
import com.smartwebee.android.blespp.utils.Utils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;

abstract public class BlockBaseActivity extends BaseActivity {
    public static String TAG = "BlockBaseActivity";
    private BluetoothLeService mBluetoothLeService;
    //蓝牙名字
    public String mDeviceName;
    //蓝牙地址
    public String mDeviceAddress;

    //发送buf数组的长度
    protected int sendDataLen = 0;
    //分段发送数据记录发送位置
    protected int sendIndex = 0;
    //发送的buf
    protected byte[] sendBuf;

    //将需要发送的数据分组
    List<byte[]> sendByteList;
    //记录延时数组的位置
    final int[] position = {0};

    //是否终止发送数据
    private boolean isStop = false;
    //调试模式发送和下载模式发送区分flag
    private boolean isDebug = true;
    //控制发送的定时器
    private Subscription timeSubscription;

    private final ServiceConnection mServiceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
            if (!mBluetoothLeService.initialize()) {
                Log.e(TAG, "Unable to initialize Bluetooth");
                finish();
            }
            // Automatically connects to the device upon successful start-up initialization.
            if (!TextUtils.isEmpty(mDeviceAddress)) {
                mBluetoothLeService.connect(mDeviceAddress);
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mBluetoothLeService = null;
        }
    };

    //和service交互的BroadcastReceiver
    private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {

            } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
                if (!TextUtils.isEmpty(mDeviceAddress)) {
                    mBluetoothLeService.connect(mDeviceAddress);
                }
            } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {

            } else if (BluetoothLeService.ACTION_GATT_SERVICES_NO_DISCOVERED.equals(action)) {
                if (!TextUtils.isEmpty(mDeviceAddress)) {
                    mBluetoothLeService.connect(mDeviceAddress);
                }
            } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
                displayData(intent.getByteArrayExtra(BluetoothLeService.EXTRA_DATA));
            } else if (BluetoothLeService.ACTION_WRITE_SUCCESSFUL.equals(action)) {
                if (sendDataLen > 0) {
                    Log.v("log", "Write OK,Send again");
                    //每20个字节延时20ms
                    if (!isStop) {
                        timeSubscription = Observable.timer(20, TimeUnit.MILLISECONDS)
                                .subscribeOn(Schedulers.newThread())
                                .observeOn(AndroidSchedulers.mainThread())
                                .subscribe(new Action1<Long>() {
                                    @Override
                                    public void call(Long aLong) {
                                        onSend();
                                    }
                                });
                    }
                } else {
                    Log.v("log", "Write Finish");
                }
            }

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
        bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
    }

    /**
     * 发送字符串到设备
     *
     * @param originStr
     */
    public void sendDataToDevice(String originStr) {
        Log.i(TAG, originStr);
        initSendBuf(BlocklyUtils.getSendStr(originStr));
        showLoading("数据发送中...");
        //开始发送之前重置发送数组的位置
        position[0] = 0;
        isStop = false;
        isDebug = false;
        delaySend();
    }

    /**
     * 发送调试模式字符串到设备
     *
     * @param originStr
     */
    public void sendDebugDataToDevice(String originStr) {
        Log.i(TAG, originStr);
        initSendBuf(BlocklyUtils.getDebugSendStr(originStr));
        showLoading("数据发送中...");
        //开始发送之前重置发送数组的位置
        position[0] = 0;
        isStop = false;
        isDebug = true;
        delaySend();
    }

    /**
     * 命令组延时发送
     */
    private void delaySend() {
        int time;
        if (isDebug) {
            if (position[0] == 0) {
                time = 1;
            } else if (position[0] == 1) {
                time = 2500;
            } else if (position[0] == 2) {
                time = 1000;
            } else if (position[0] == 3) {
                time = 2500;
            } else {
                time = 1000;
            }
        } else {
            if (position[0] == 0) {
                time = 1;
            } else if (position[0] == 1) {
                time = 2500;
            } else {
                time = 1000;
            }
        }

        if (!isStop) {
            timeSubscription = Observable.timer(time, TimeUnit.MILLISECONDS)
                    .subscribeOn(Schedulers.newThread())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Action1<Long>() {
                        @Override
                        public void call(Long aLong) {
                            Log.i("mySend", Utils.asciiToString(sendByteList.get(position[0])));
                            //初始化当前要发送的byte数组
                            sendBuf = sendByteList.get(position[0]);
                            sendDataLen = sendBuf.length;
                            onSend();
                        }
                    });
        }

    }

    private void onSend() {
        if (sendDataLen > 20) {
            final byte[] buf = new byte[20];
            for (int i = 0; i < 20; i++) {
                buf[i] = sendBuf[sendIndex + i];
            }
            sendIndex += 20;
            mBluetoothLeService.writeData(buf);
            sendDataLen -= 20;
        } else {
            final byte[] buf = new byte[sendDataLen];
            for (int i = 0; i < sendDataLen; i++) {
                buf[i] = sendBuf[sendIndex + i];
            }
            mBluetoothLeService.writeData(buf);
            sendDataLen = 0;
            sendIndex = 0;
            position[0]++;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    httpLoading.setProgress(100 * position[0] / sendByteList.size());
                    httpLoading.setEvent(new LoadingDismissEvent() {
                        @Override
                        public void clickEvent() {
                            isStop = true;
                            timeSubscription.unsubscribe();
                        }
                    });
                }
            });
            if (position[0] < sendByteList.size()) {
                delaySend();
            } else {
                dismissLoading();
                whenDismissLoading();
            }
        }
    }

    protected void whenDismissLoading() {

    }

    /**
     * 显示硬件返回
     *
     * @param buf 硬件返回byte数组
     */
    abstract protected void displayData(byte[] buf);

    /**
     * 将字符传转为byte数组
     *
     * @param originStr 原始字符串
     */
    private void initSendBuf(String originStr) {
        sendIndex = 0;
        String[] sendStrArray = BlocklyUtils.getHexString(originStr).split("0a");
        sendByteList = new ArrayList<>();
        for (int i = 0; i < sendStrArray.length; i++) {
            if (sendStrArray[i].equals("03") || sendStrArray[i].equals("04")) {
                sendByteList.add(BlocklyUtils.stringToBytes(sendStrArray[i]));
            } else {
                sendByteList.add(BlocklyUtils.stringToBytes(sendStrArray[i] + "0d0a"));
            }

        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
        if (mBluetoothLeService != null) {
            if (!TextUtils.isEmpty(mDeviceAddress)) {
                final boolean result = mBluetoothLeService.connect(mDeviceAddress);
                Log.d(TAG, "Connect request result=" + result);
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(mGattUpdateReceiver);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mServiceConnection);
        mBluetoothLeService = null;
    }
}
